﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;

namespace GONES.Tools.Common
{
    public class Core
    {
        /// <summary>
        /// 跟据ID号生成单号 前三位为系统标识,中间为自增序列（不足八位补全八位,不是偶数长度在前补0）,最后一位为校验位
        /// </summary>
        /// <param name="billsPrefix"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static string BuildBillsNumber(string billsPrefix, long id)
        {
            if (billsPrefix.Length != 3)
            {
                throw new Exception("单据前缀不正确");
            }

            string strId = id.ToString().PadLeft(id.ToString().Length >= 8 ? id.ToString().Length : 8, '0');
            if (strId.Length%2 != 0)
                strId = "0" + strId;

            strId = billsPrefix + strId;

            return strId + BuildValidateNumber(strId);
        }

        public static bool CheckBillsNumber(string billsNumber)
        {
            if (billsNumber.Length < 12 || billsNumber.Length%2 != 0)
                return false;

            string sourceNumber = billsNumber.Substring(0, billsNumber.Length - 1);
            int validateNumber = int.Parse(billsNumber[billsNumber.Length - 1].ToString());

            return BuildValidateNumber(sourceNumber) == validateNumber;
        }

        public static string BuildSelfCode(string billsPrefix, long id)
        {
            //TODO:生成自编号，要调整
            if (billsPrefix.Length != 3)
            {
                throw new Exception("前缀不正确");
            }

            string strId = id.ToString().PadLeft(id.ToString().Length >= 8 ? id.ToString().Length : 8, '0');
            if (strId.Length%2 != 0)
                strId = "0" + strId;

            strId = billsPrefix + strId;

            return strId + BuildValidateNumber(strId);
        }

        public static int BuildValidateNumber(string source)
        {
            int odd = 0;
            int even = 0;

            for (int i = source.Length - 1; i > 0; i--)
            {
                if ((source.Length - i)%2 == 1)
                {
                    odd += int.Parse(source[i].ToString());
                }
                else
                {
                    even += int.Parse(source[i].ToString());
                }
            }

            return (10 - (odd*3 + even)%10)%10;
        }

        public static bool TestGrant(Dictionary<int, long> grant, string position)
        {
            if (string.IsNullOrEmpty(position))
                return false;

            if (grant == null)
                return false;

            string[] ts = position.Split(new char[] {' ', '\r', '\n', '\t', ',', ';', '|', '/'},
                                         StringSplitOptions.RemoveEmptyEntries);
            if (ts.Length != 2)
                return false;

            int bit;
            int index;

            if (!int.TryParse(ts[0], out index))
                return false;

            if (!int.TryParse(ts[1], out bit))
                return false;

            if (!grant.ContainsKey(index))
                return false;

            if (grant[index] >= 0)
            {
                long value = 0;
                value = 2 ^ bit;
                return (grant[index] & value) == value;
            }

            return true;
        }

        public static bool SetGrant(string position, bool value, ref Dictionary<int, long> grant)
        {
            if (string.IsNullOrEmpty(position))
                return false;

            if (grant == null)
                return false;

            string[] ts = position.Split(new char[] {' ', '\r', '\n', '\t', ',', ';', '|', '/'},
                                         StringSplitOptions.RemoveEmptyEntries);
            if (ts.Length != 2)
                return false;

            int bit;
            int index;

            if (!int.TryParse(ts[0], out index))
                return false;

            if (!int.TryParse(ts[1], out bit))
                return false;

            long v = 2 ^ bit;

            if (value)
                grant[index] = grant[index] | v;
            else if ((grant[index] & v) == v)
                grant[index] = grant[index] ^ v;

            return true;
        }

        public static string ResolveRemotUrl(string localUrl)
        {
            if (string.IsNullOrEmpty(localUrl))
            {
                return localUrl;
            }

            if (string.IsNullOrEmpty(GlobalSettings.Instance.FileServerUrl))
            {
                return ResolveUrl(localUrl);
            }
            else
            {
                if (localUrl.IndexOf(GlobalSettings.Instance.FileServerUrl) >= 0)
                {
                    return ResolveUrl(localUrl);
                }
                return GlobalSettings.Instance.FileServerUrl.EndsWith("/")
                           ? GlobalSettings.Instance.FileServerUrl + localUrl.Replace(@"~/", "")
                           : GlobalSettings.Instance.FileServerUrl + localUrl.Replace("~", "");
            }
        }

        /// <summary>
        /// 1、当URL以斜线开始（/或\），也不会改动它！
        /// 2、当URL以〜/开始，它会被AppVirtualPath取代。
        /// 3、当URL是一个绝对URL，也不会改变它。
        /// 4、在任何其他情况下（甚至以〜开始，而不是斜杠），将追加URL到AppVirtualPath。
        /// 5、每当它修改URL，还修复斜杠。删除双斜线，用/替换\。
        /// </summary>
        /// <param name="relativeUrl"></param>
        /// <returns></returns>
        public static string ResolveUrl(string relativeUrl)
        {
            if (relativeUrl == null) throw new ArgumentNullException("relativeUrl");

            if (relativeUrl.Length == 0 || relativeUrl[0] == '/' ||
                relativeUrl[0] == '\\') return relativeUrl;

            int idxOfScheme =
                relativeUrl.IndexOf(@"://", StringComparison.Ordinal);
            if (idxOfScheme != -1)
            {
                int idxOfQM = relativeUrl.IndexOf('?');
                if (idxOfQM == -1 || idxOfQM > idxOfScheme) return relativeUrl;
            }

            StringBuilder sbUrl = new StringBuilder();
            sbUrl.Append(HttpRuntime.AppDomainAppVirtualPath);
            if (sbUrl.Length == 0 || sbUrl[sbUrl.Length - 1] != '/') sbUrl.Append('/');

            // found question mark already? query string, do not touch!
            bool foundQM = false;
            bool foundSlash; // the latest char was a slash?
            if (relativeUrl.Length > 1
                && relativeUrl[0] == '~'
                && (relativeUrl[1] == '/' || relativeUrl[1] == '\\'))
            {
                relativeUrl = relativeUrl.Substring(2);
                foundSlash = true;
            }
            else foundSlash = false;
            foreach (char c in relativeUrl)
            {
                if (!foundQM)
                {
                    if (c == '?') foundQM = true;
                    else
                    {
                        if (c == '/' || c == '\\')
                        {
                            if (foundSlash) continue;
                            else
                            {
                                sbUrl.Append('/');
                                foundSlash = true;
                                continue;
                            }
                        }
                        else if (foundSlash) foundSlash = false;
                    }
                }
                sbUrl.Append(c);
            }

            return sbUrl.ToString();
        }
    }
}